package jp.seraph.same.core;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.net.InetSocketAddress;

import javax.swing.JFileChooser;
import javax.swing.JFrame;

import jp.seraph.jsade.action.NaoActionCreator;
import jp.seraph.jsade.core.AgentContext;
import jp.seraph.jsade.core.AgentRunner;
import jp.seraph.jsade.core.DefaultAgentContext;
import jp.seraph.jsade.core.DefaultAgentRunner;
import jp.seraph.jsade.core.DefaultWorld;
import jp.seraph.jsade.core.NopSeeObjectCalculator;
import jp.seraph.jsade.model.nao.NaoJointIdentifierContainer;
import jp.seraph.jsade.model.nao.NaoModelManager;
import jp.seraph.jsade.model.nao.NaoObjectContainer;
import jp.seraph.jsade.task.TaskSelectorAgent;
import jp.seraph.jsmf.codec.FileMotionManager;
import jp.seraph.jsmf.codec.OldMotionCodec;
import jp.seraph.jspf.codec.FilePoseManager;
import jp.seraph.jspf.codec.JsonPoseCodec;
import jp.seraph.jspf.pose.DefaultPose;
import jp.seraph.jspf.pose.PoseManager;
import jp.seraph.jspf.utils.NaoSymmetricJointContext;
import jp.seraph.jspf.utils.PoseUtil;
import jp.seraph.same.controller.DefaultAgentController;
import jp.seraph.same.controller.DefaultMotionController;
import jp.seraph.same.controller.DefaultPoseController;
import jp.seraph.same.model.AgentModel;
import jp.seraph.same.model.DefaultAgentModel;
import jp.seraph.same.model.DefaultMotionCollectionModel;
import jp.seraph.same.model.DefaultPoseCollectionModel;
import jp.seraph.same.model.MotionCollectionModel;
import jp.seraph.same.model.NaoJointPositionMapper;
import jp.seraph.same.model.PoseCollectionModel;
import jp.seraph.same.view.MainPanel;
import jp.seraph.same.view.MotionPanel;
import jp.seraph.same.view.PosePanel;

public class MotionEditorRunner {
    private static String POSE_DIR = "Pose";
    private static String Motion_DIR = "Motion";
    private static String ZERO_POZE = "zero";
    private static String ZERO_MOTION = "zero";

    /**
     * @param args
     */
    public static void main(String[] args) {
        String tIPAddress = "127.0.0.1";
        int tPort = 3100;
        if (args.length == 2) {
            tIPAddress = args[0];
            tPort = Integer.parseInt(args[1]);
        }

        JFileChooser tDirChooser = new JFileChooser();
        tDirChooser.setDialogTitle("ポーズとモーションを保存するディレクトリを選択してください。");
        tDirChooser.setDialogType(JFileChooser.OPEN_DIALOG);
        tDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        tDirChooser.setMultiSelectionEnabled(false);
        tDirChooser.setCurrentDirectory(new File("."));
        int tResult = tDirChooser.showOpenDialog(null);

        if (tResult != JFileChooser.APPROVE_OPTION)
            return;

        File tRootDirectory = tDirChooser.getSelectedFile();
        FilePoseManager tPoseManager = new FilePoseManager(new File(tRootDirectory, POSE_DIR), new JsonPoseCodec(new NaoJointIdentifierContainer()), true);
        FileMotionManager tMotionManager = new FileMotionManager(new File(tRootDirectory, Motion_DIR), new OldMotionCodec(tPoseManager, new NaoJointIdentifierContainer()));

        if (!tPoseManager.containsPose(ZERO_POZE))
            tPoseManager.setPose(ZERO_POZE, new DefaultPose(new NaoJointIdentifierContainer()));

        DefaultAgentModel tAgentModel = new DefaultAgentModel();
        EditorMotionSelector tSelector = new EditorMotionSelector();
        EditorAgent tAgent = new EditorAgent(tAgentModel, tSelector);
        tAgentModel.init(tAgent);
        DefaultAgentRunner tRunner = createRunner(tAgent, new InetSocketAddress(tIPAddress, tPort));
        JFrame tFrame = createMainForm(tRunner, tAgent, tAgentModel, tPoseManager, tMotionManager, tSelector);

        tFrame.setVisible(true);
        tRunner.startAgent();
        try {
            tRunner.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("終了しました");
        System.exit(0);
    }

    private static JFrame createMainForm(final AgentRunner aRunner, TaskSelectorAgent aAgent, AgentModel aAgentModel, FilePoseManager aPoseManager, FileMotionManager aMotionManager, EditorMotionSelector aSelector) {
        PoseCollectionModel tPoseModel = new DefaultPoseCollectionModel(aPoseManager, new NaoObjectContainer(), new NaoJointIdentifierContainer(), new NaoJointPositionMapper());
        MotionCollectionModel tMotionModel = new DefaultMotionCollectionModel(aMotionManager, aPoseManager, new NaoJointIdentifierContainer(), tPoseModel, ZERO_MOTION);
        MotionPanel tMotionPanel = new MotionPanel(tMotionModel, tPoseModel, new DefaultMotionController(aSelector, tMotionModel));
        PosePanel tPosePanel = new PosePanel(tPoseModel, new DefaultPoseController(tPoseModel, aSelector, new PoseUtil(new NaoSymmetricJointContext()), new DefaultPose(new NaoJointIdentifierContainer())));

        JFrame tFrame = new MainPanel(new DefaultAgentController(aSelector, new NaoActionCreator()), aAgentModel, tPosePanel, tMotionPanel);
        tFrame.setSize(600, 400);

        tFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        tFrame.addWindowListener(new WindowListener() {

            public void windowActivated(WindowEvent aE) {
            }

            public void windowClosed(WindowEvent aE) {
                aRunner.stopAgent();
            }

            public void windowClosing(WindowEvent aE) {
            }

            public void windowDeactivated(WindowEvent aE) {
            }

            public void windowDeiconified(WindowEvent aE) {
            }

            public void windowIconified(WindowEvent aE) {
            }

            public void windowOpened(WindowEvent aE) {
            }
        });

        return tFrame;
    }

    private static DefaultAgentRunner createRunner(TaskSelectorAgent aAgent, InetSocketAddress aAddress) {
        AgentContext tContext = new DefaultAgentContext(aAddress, "MotionEditorAgent", 1, AgentContext.NAO_MODEL_INITIALIZER);
        DefaultAgentRunner tRunner = new DefaultAgentRunner(new DefaultWorld(new NaoModelManager(0), new NopSeeObjectCalculator()), tContext, aAgent);

        return tRunner;
    }
}
